<!DOCTYPE html>
<html>
<!--
Copyright 2009 The Closure Library Authors. All Rights Reserved.

Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<!--
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Closure Unit Tests - goog.ui.media.FlashObject</title>
<script src="../../base.js"></script>
<script>
  goog.require('goog.dom');
  goog.require('goog.dom.DomHelper');
  goog.require('goog.events');
  goog.require('goog.events.EventTarget');
  goog.require('goog.log');
  goog.require('goog.testing.LooseMock');
  goog.require('goog.testing.MockClassFactory');
  goog.require('goog.testing.MockControl');
  goog.require('goog.testing.events');
  goog.require('goog.testing.jsunit');
  goog.require('goog.ui.Component');
  goog.require('goog.ui.media.FlashObject');
</script>
</head>
<body>
<script>

  var FLASH_URL = 'http://www.youtube.com/v/RbI7cCp0v6w&hl=en&fs=1';
  var control = new goog.testing.MockControl();
  var domHelper = control.createLooseMock(goog.dom.DomHelper);
  // TODO(user): mocking window.document throws exceptions in FF2. find out how
  // to mock it.
  var documentHelper = {body: control.createLooseMock(goog.dom.DomHelper)};
  var element = goog.dom.createElement('div');

  function setUp() {
    control.$resetAll();
    domHelper.getDocument().$returns(documentHelper).$anyTimes();
    domHelper.createElement('div').$returns(element).$anyTimes();
    documentHelper.body.appendChild(element).$anyTimes();
  }

  function tearDown() {
    control.$verifyAll();
  }

  function getFlashVarsFromElement(flash) {
    var el = flash.getFlashElement();

    // This should work in everything except IE:
    if (el.hasAttribute && el.hasAttribute('flashvars'))
      return el.getAttribute('flashvars');

    // For IE: find and return the value of the correct param element:
    el = el.firstChild;
    while (el) {
      if (el.name == 'FlashVars') {
        return el.value;
      }
      el = el.nextSibling;
    }
    return '';
  }

  function testInstantiationAndRendering() {
    control.$replayAll();

    var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    flash.render();
    flash.dispose();
  }

  function testSetFlashVar() {
    control.$replayAll();

    var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);

    assertTrue(flash.getFlashVars().isEmpty());
    flash.setFlashVar('foo', 'bar');
    flash.setFlashVar('hello', 'world');
    assertFalse(flash.getFlashVars().isEmpty());

    flash.render();

    assertEquals('foo=bar&hello=world', getFlashVarsFromElement(flash));
    flash.dispose();
  }

  function testAddFlashVars() {
    control.$replayAll();

    var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);

    assertTrue(flash.getFlashVars().isEmpty());
    flash.addFlashVars({
      'using': 'an',
      'object': 'literal'
    });
    assertFalse(flash.getFlashVars().isEmpty());

    flash.render();

    assertEquals('using=an&object=literal', getFlashVarsFromElement(flash));
    flash.dispose();
  }

  /**
   * @deprecated Remove once setFlashVars is removed.
   */
  function testSetFlashVarsUsingFalseAsTheValue() {
    control.$replayAll();

    var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);

    assertTrue(flash.getFlashVars().isEmpty());
    flash.setFlashVars('beEvil', false);
    assertFalse(flash.getFlashVars().isEmpty());

    flash.render();

    assertEquals('beEvil=false', getFlashVarsFromElement(flash));
    flash.dispose();
  }

  /**
   * @deprecated Remove once setFlashVars is removed.
   */
  function testSetFlashVarsWithWrongArgument() {
    control.$replayAll();

    assertThrows(function() {
      var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
      flash.setFlashVars('foo=bar');
      flash.dispose();
    });
  }

  function testSetFlashVarUrlEncoding() {
    control.$replayAll();

    var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    flash.setFlashVar('foo', 'bar and some extra spaces');
    flash.render();
    assertEquals('foo=bar%20and%20some%20extra%20spaces',
        getFlashVarsFromElement(flash));
    flash.dispose();
  }

  function testThrowsRequiredVersionOfFlashNotAvailable() {
    control.$replayAll();

    var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    flash.setRequiredVersion('999.999.999');

    assertTrue(flash.hasRequiredVersion());

    assertThrows(function() {
      flash.render();
    });

    flash.dispose();
  }

  function testIsLoadedAfterDispose() {
    control.$replayAll();

    var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    flash.render();
    // TODO(user): find out a way to test the loadness of flash movies on
    // asynchronous tests. if debugger; is left here, the test pass. if removed
    // the test fails. that happens because flash needs some time to be
    // considered loaded, after flash.render() is called (like img.src i guess).
    //debugger;
    //assertTrue(flash.isLoaded());
    flash.dispose();
    assertFalse(flash.isLoaded());
  }

  function testXssAttacks() {
    control.$replayAll();

    called = false;
    var injection = '' +
        '">' +
        '</embed>' +
        '<script>called = true; // evil arbitrary js injected here<\/script>' +
        '<embed src="';
    var flash = new goog.ui.media.FlashObject(injection, domHelper);
    flash.render();
    // Makes sure FlashObject html escapes user input.
    // NOTE(user): this test fails if the URL is not HTML escaped, showing that
    // html escaping is necessary to avoid attacks.
    assertFalse(called);
  }

  function testPropagatesEventsConsistently() {
    var event = control.createLooseMock(goog.events.Event);

    // we expect any event to have its propagation stopped.
    event.stopPropagation();

    control.$replayAll();

    var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    flash.render();
    event.target = flash.getElement();
    event.type = goog.events.EventType.CLICK;
    goog.testing.events.fireBrowserEvent(event);
    flash.dispose();
  }

  function testEventsGetsSinked() {
    var called = false;
    var flash = new goog.ui.media.FlashObject(FLASH_URL);
    var parent = goog.dom.createElement('div');
    flash.render(parent);

    goog.events.listen(parent, goog.events.EventType.CLICK, function(e) {
      called = true;
    });

    assertFalse(called);

    goog.testing.events.fireClickSequence(flash.getElement());

    assertFalse(called);
    flash.dispose();
  }
</script>
</body>
</html>
